
`include "common_header.verilog"

//  *************************************************************************
//  File : p8264_block_type_decode.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2012 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Daniel Koehler
//  info@morethanip.com
//  *************************************************************************
//  Description : 40/100G Base-R PCS Receive: single block type and decode.
//                Does only perform the block decoding to CGMII but no
//                checking, which is done by the receive statemachine following
//                this per-block decoding to mask it with error eventually.
//  Version     : $Id: p8264_block_type_decode.v,v 1.4 2015/04/02 00:57:14 dk Exp $
//  *************************************************************************

module p8264_block_type_decode (
   
   reset,
   clk,
   clk_ena,
   data_in,
   sh_in,
   clk_ena_out,
   rx_d,
   rx_c,
   r_type_c,
`ifdef MTIPPCS_EEE_ENA
        r_type_li,
`endif
   r_type_s,
   r_type_t,
   xlgmii_rxt0_next,
   r_type_d,
   r_type_edt);

input   reset;          //  asynch reset
input   clk;            //  system clock
input   clk_ena;        //  clock enable
input   [63:0] data_in; //  data input
input   [1:0] sh_in;    //  Sync header
output  clk_ena_out;    //  clock enable - delay depending on pipelines
output  [63:0] rx_d;    //  CGMII data
output  [7:0] rx_c;     //  CGMII control
output  r_type_c;       //  C Block type received
`ifdef MTIPPCS_EEE_ENA
output  r_type_li;
`endif
output  r_type_s;       //  S Block type received
output  r_type_t;       //  T Block type received
output  xlgmii_rxt0_next;//  Advance indication if TERM block without data is next after current 
                         // (directly from decoder classification block type 0x87, T0)       
output  r_type_d;       //  D Block type received
output  r_type_edt;     //  E or D or T Block type received

reg     clk_ena_out; 
wire    [63:0] rx_d; 
wire    [7:0] rx_c; 
reg     r_type_c; 
`ifdef MTIPPCS_EEE_ENA
reg     r_type_li;
`endif
reg     r_type_s; 
reg     r_type_t; 
reg     xlgmii_rxt0_next; 
reg     r_type_d; 
reg     r_type_edt; 

wire    r_type_c_int;           //  C Block type received
`ifdef MTIPPCS_EEE_ENA
wire    r_type_li_int;
`endif
wire    r_type_s_int;           //  S Block type received
wire    r_type_t_int;           //  T Block type received
wire    xlgmii_rxt0_next_int;
wire    r_type_d_int;           //  D Block type received
wire    r_type_edt_int;         //  E or D or T Block type received
wire    [3:0] class_block;

//  ------------------------
//  combinatorial classifier
//  ------------------------

//
// use the block_type with a true pipeline delay instead of a clock-enable delay
//
block_type_10l U_BT (

          .data_in(data_in),
          .sh_in(sh_in),
          .class_block(class_block),
          `ifdef MTIPPCS_EEE_ENA 
          .r_type_li(r_type_li_int),
          `endif 
          .r_type_c(r_type_c_int),
          .r_type_s(r_type_s_int),
          .r_type_t(r_type_t_int),
          .r_type_d(r_type_d_int));

assign xlgmii_rxt0_next_int = (class_block == 4'b 1000 && r_type_t_int==1'b 1) ? 1'b 1 : 1'b 0; 
assign r_type_edt_int = ((r_type_c_int==1'b 0 && r_type_s_int==1'b 0 && r_type_t_int==1'b 0 && r_type_d_int==1'b 0
                          `ifdef MTIPPCS_EEE_ENA
                          && r_type_li_int == 1'b 0
                          `endif
                         ) | // no type detected=error type
			 r_type_t_int==1'b 1 | r_type_d_int==1'b 1) ? 1'b 1 : 1'b 0;

//  --------------------------
//  decoder (registered ouput)
//  --------------------------


block_decode_10l U_DEC (

   .reset(reset),
   .sw_reset(1'b 0),
   .ck_161(clk),
   .ck_ena(1'b 1),
   .data_in(data_in),
   .class_block(class_block),
   .decode(1'b 1),
   .error(1'b 0),
`ifdef MTIPPCS_EEE_ENA   
   .lpi_seq_force(1'b 0),
`endif   
   .rx_d_out(rx_d),
   .rx_c_out(rx_c),
   .rx_val());


// ------------------------
// pipeline register. Its a true pipeline, hence output is valid 1 clock cycle later.
// ------------------------

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      clk_ena_out <= 1'b 0;	
      r_type_c <= 1'b 0;	
`ifdef MTIPPCS_EEE_ENA
      r_type_li <= 1'b0;
`endif
      r_type_s <= 1'b 0;	
      r_type_t <= 1'b 0;	
      xlgmii_rxt0_next <= 1'b0;
      r_type_d <= 1'b 0;	
      r_type_edt <= 1'b 0;	
      end
   else // NO clock enable here!
      begin

        //  true clock pipeline!
      clk_ena_out <= clk_ena;	

        //  register all data and attributes	
      r_type_c <= r_type_c_int;	
`ifdef MTIPPCS_EEE_ENA
      r_type_li <= r_type_li_int;
`endif

      r_type_s <= r_type_s_int;	
      r_type_t <= r_type_t_int;	
      xlgmii_rxt0_next <= xlgmii_rxt0_next_int; 
      r_type_d <= r_type_d_int;	
      r_type_edt <= r_type_edt_int;	
      end
   end

endmodule // module p8264_block_type_decode

